/*
* Copyright (C) 2010-2012 Magnus Skjegstad
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* 
* The latest version of this library can be downloaded from http://mist-pubsub.googlecode.com
* 
*/
package com.skjegstad.mist2.modules.udp;

import com.skjegstad.mist2.datatypes.DataFragment;
import com.skjegstad.mist2.datatypes.NodeIdentifier;
import com.skjegstad.mist2.datatypes.TopicIdentifier;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.LinkedList;

/**
 *
 * @author magnus
 */
public class DataFragmentMessage implements Externalizable {
    private DataFragment fragment;

    public DataFragmentMessage(DataFragment fragment) {
        this.fragment = fragment;
    }

    public DataFragmentMessage() {
    }

    public DataFragment getFragment() {
        return fragment;
    }

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        NodeIdentifier nodeId = new NodeIdentifier(in.readLong());
        long seqNr = in.readLong();
        long age = in.readLong();
        long expireTime = in.readLong();
        int fragmentNo = in.readInt();
        boolean lastFrag = in.readBoolean();
        long completeHash = in.readLong();

        TopicIdentifier topic;
        {
            byte topicLen = in.readByte();
            LinkedList<Integer> topics = new LinkedList();
            for (int i = 0; i < topicLen; i++)
                topics.add(in.readInt());
            topic = new TopicIdentifier(topics);
        }

        int dataLen = in.readInt();
        byte[] data = new byte[dataLen];

        //in.readFully(data);
        int offset = 0;
            int read = 0;
            while (read > -1 && offset < data.length) {
                read = in.read(data, offset, data.length-offset);
                if (read > 0)
                    offset = offset + read;
            }

        this.fragment = new DataFragment(nodeId, seqNr, data, topic, age, expireTime, fragmentNo, lastFrag, completeHash);
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeLong(this.fragment.getSourceNode().getNodeIdentifier());
        out.writeLong(this.fragment.getSeqNr());
        out.writeLong(this.fragment.getAge());
        out.writeLong(this.fragment.getExpireTime());
        out.writeInt(this.fragment.getFragmentNo());
        out.writeBoolean(this.fragment.isLastFragment());
        out.writeLong(this.fragment.getCompleteHash());

        out.writeByte(this.fragment.getTopic().getHashes().size());
        for (int i : this.fragment.getTopic().getHashes())
            out.writeInt(i);

        out.writeInt(this.fragment.getPayloadLen());
        out.write(this.fragment.getPayload());
    }

    @Override
    public String toString() {
        return "n_id:" + fragment.getSourceNode() + "/t:" + fragment.getTopic() + "/f#:" + fragment.getFragmentNo() + "/last:" + fragment.isLastFragment();
    }

}
